Passed
Branch next (4c1157)
by Apocist
01:28
created

nodeVBulletinAPI.js ➔ __initialize   B

Complexity

Conditions 1
Paths 320

Size

Total Lines 71
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 1
eloc 50
c 3
b 0
f 0
nc 320
nop 1
dl 0
loc 71
rs 8.6363

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
'use strict';
2
const md5 = require('js-md5'),
3
    request = require('request'),
4
    _ = require('underscore'),
5
    Forum = require('./Forum'),
6
    Inbox = require('./Inbox'),
7
    Member = require('./Member'),
8
    Message = require('./Message'),
9
    Post = require('./Post'),
10
    Thread = require('./Thread'),
11
    uuidV1 = require('uuid/v1'),
12
    {version} = require('./package.json');
13
14
/**
15
 *
16
 */
17
class VBApi {
18
    /**
19
     * Initialize a vb api connection .This needs to be called for the first time
20
     * @param {string} apiUrl
21
     * @param {string} apiKey
22
     * @param {string} platformName
23
     * @param {string} platformVersion
24
     * @param {object=} options - A fallback to the old style config
25
     * @param {string=} options.apiUrl
26
     * @param {string=} options.apiKey
27
     * @param {string=} options.platformName
28
     * @param {string=} options.platformVersion
29
     */
30
    constructor(apiUrl, apiKey, platformName, platformVersion, options) {
31
        this.defaultVars = {
32
            baseUrl: '', //Needed for cookie related commands
33
            apiUrl: '',
34
            apiKey: '',
35
            clientName: 'nodeVBulletinAPI',
36
            clientVersion: version,
37
            uniqueId: ''
38
        };
39
40
        this.clientSessionVars = {
41
            apiVersion: '',
42
            apiAccessToken: '',
43
            sessionHash: '', // Unused?
44
            apiClientId: '',
45
            secret: '',
46
            inited: false,
47
            error: null
48
        };
49
50
        /**
51
         * @typedef UserVars
52
         * @property {string} dbsessionhash
53
         * @property {number} userid
54
         * @property {string} username
55
         * @property {boolean} loggedIn
56
         * @type {UserVars}
57
         */
58
        this.userSessionVars = {
59
            dbsessionhash: '',
60
            username: '',
61
            userid: 0,
62
            loggedIn: false
63
        };
64
65
        /** @private */
66
        this.__waitingForInitializationCallback = function () {
67
        }; // A blank callback to be filled in
68
69
        options = options || {};
70
        options.apiUrl = apiUrl || options.apiUrl || '';
71
        options.apiKey = apiKey || options.apiKey || '';
72
        options.platformName = platformName || options.platformName || '';
73
        options.platformVersion = platformVersion || options.platformVersion || '';
74
75
        if (
76
            options.apiUrl !== ''
77
            && options.apiUrl !== ''
78
            && options.platformName !== ''
79
            && options.platformVersion !== ''
80
        ) {
81
            this.__initialize(options);
82
        } else {
83
            this.clientSessionVars.error = 'apiInit(): Initialization requires a `apiUrl`, `apiKey`, `platformName`, and `platformVersion`';
84
            this.__waitingForInitializationCallback(false);
85
        }
86
    }
87
88
    /**
89
     * Initialize a vb api connection. This needs to be called for the first time
90
     * @param {object} options
91
     * @param {string} options.apiUrl
92
     * @param {string} options.apiKey
93
     * @param {string} options.platformName
94
     * @param {string} options.platformVersion
95
     * @private
96
     */
97
    __initialize(options) {
98
        let that = this;
99
        // Run itself as a self invoked promise that is awaited by nothing. callMethod shall wait until this is finished
100
        (async function __initialize_self() {
101
            let error = null;
102
            let result = null;
103
            let regex_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;
104
            let url_parts = regex_url.exec(options.apiUrl);
105
            that.defaultVars.baseUrl = that.defaultVars.baseUrl || url_parts[1] + ':' + url_parts[2] + url_parts[3] + '/';
106
            that.defaultVars.apiUrl = that.defaultVars.apiUrl || options.apiUrl;
107
            that.defaultVars.apiKey = that.defaultVars.apiKey || options.apiKey;
108
            that.defaultVars.uniqueId = that.defaultVars.uniqueId || md5(that.defaultVars.clientName + that.defaultVars.clientVersion + options.platformName + options.platformVersion + uuidV1() + new Date().getTime());
109
110
            try {
111
                /**
112
                 *
113
                 * @type {{}}
114
                 * @property {string} apiversion
115
                 * @property {string} apiaccesstoken
116
                 * @property {string} sessionhash
117
                 * @property {string} apiclientid
118
                 * @property {string} secret
119
                 */
120
                let response = await that.callMethod({
121
                    method: 'api_init',
122
                    params: {
123
                        clientname: that.defaultVars.clientName,
124
                        clientversion: that.defaultVars.clientVersion,
125
                        platformname: options.platformName,
126
                        platformversion: options.platformVersion,
127
                        uniqueid: that.defaultVars.uniqueId
128
                    }
129
                });
130
131
                that.clientSessionVars.apiVersion = '';
132
                that.clientSessionVars.apiAccessToken = '';
133
                that.clientSessionVars.sessionHash = '';
134
                that.clientSessionVars.apiClientId = '';
135
                that.clientSessionVars.secret = '';
136
                that.clientSessionVars.inited = false;
137
                if (
138
                    response.apiversion
139
                    && response.apiaccesstoken
140
                    && response.sessionhash
141
                    && response.apiclientid
142
                    && response.secret
143
                ) {
144
                    that.clientSessionVars.apiVersion = response.apiversion;
145
                    that.clientSessionVars.apiAccessToken = response.apiaccesstoken;
146
                    that.clientSessionVars.sessionHash = response.sessionhash;
147
                    that.clientSessionVars.apiClientId = response.apiclientid;
148
                    that.clientSessionVars.secret = response.secret;
149
                    that.clientSessionVars.inited = true;
150
                    that.__waitingForInitializationCallback(true);
151
                    result = that;
152
                }
153
154
                if (result === null) {
155
                    that.clientSessionVars.error = that.constructor.parseErrorMessage(response) || 'TODO ERROR (api connection did not return a session)';
156
                    that.__waitingForInitializationCallback(false);
157
                    error = that.clientSessionVars.error;
158
                }
159
            } catch (e) {
160
                that.clientSessionVars.error = e;
161
                that.__waitingForInitializationCallback(false);
162
                // reject(e);
163
                error = e;
164
            }
165
            return error || result;
166
        }());
167
    }
168
169
    /**
170
     * Will return after #initialize() is complete. Otherwise may reject() after 15 second timeout
171
     * @param {number=5} waitTime
172
     * @returns {Promise<void>}
173
     * @fulfill {void}
174
     * @reject {string} - Error Reason
175
     */
176
    async waitForInitialization(waitTime) {
177
        let that = this;
178
        waitTime = waitTime || 5;
179
        return new Promise(async function (resolve, reject) {
180
            if (that.clientSessionVars.inited === true) {
181
                resolve();
182
            } else if (that.clientSessionVars.error !== null) {
183
                reject(that.clientSessionVars.error);
184
            } else {
185
                /**
186
                 * @type {number}
187
                 * @private
188
                 */
189
                that.__waitingForInitializationTimeout = setTimeout(
190
                    function () {
191
                        that.__waitingForInitializationCallback = function () {
192
                        }; // Set back to a blank function
193
                        if (that.clientSessionVars.inited === true) {
194
                            resolve();
195
                        } else {
196
                            reject('Connection could not be achieved due to timed out', that.clientSessionVars.error);
197
                        }
198
199
                    },
200
                    waitTime * 1000 // x second timeout
201
                );
202
                /**
203
                 * @param {boolean=true} success
204
                 * @private
205
                 */
206
                that.__waitingForInitializationCallback = function (success) {
207
                    if (that.__waitingForInitializationTimeout) {
208
                        clearTimeout(that.__waitingForInitializationTimeout);
209
                    }
210
                    if (success === false) {
211
                        reject(that.clientSessionVars.error);
212
                    } else {
213
                        resolve();
214
                    }
215
                };
216
            }
217
        })
218
    }
219
220
    /**
221
     *
222
     * @param {object} options
223
     * @param {string} options.method - Required action to take
224
     * @param {object<string,string>} [options.params={}] - Optional parameter variables
225
     * @param {?object<string,string>} [options.cookies] - Optional cookie variables
226
     * @returns {Promise<{}>}
227
     * @fulfill {{}}
228
     * @reject {string} - Error Reason
229
     */
230
    async callMethod(options) {
231
        let that = this;
232
        let sign = true;
233
        options = options || {};
234
        options.params = options.params || {};
235
        return new Promise(async function (resolve, reject) {
236
            try {
237
                if (!options.method) {
238
                    reject('callMethod(): requires a supplied method');
239
                    return;
240
                }
241
242
                // Sign all calls except for api_init
243
                if (options.method === 'api_init') {
244
                    sign = false;
245
                }
246
247
                // await a valid session before continuing (skipping waiting on __initialize())
248
                if (sign === true) {
249
                    await that.waitForInitialization();
250
                }
251
252
                // Gather our sessions variables together
253
                let reqParams = {
254
                    api_m: options.method,
255
                    api_c: that.clientSessionVars.apiClientId, //clientId
256
                    api_s: that.clientSessionVars.apiAccessToken, //apiAccessToken (may be empty)
257
                    api_v: that.clientSessionVars.apiVersion //api version
258
                };
259
                _.extend(reqParams, options.params); // Combine the arrays
260
261
                if (sign === true) {
262
                    // Generate a signature to validate that we are authenticated
263
                    if (that.clientSessionVars.inited) {
264
                        reqParams.api_sig = md5(that.clientSessionVars.apiAccessToken + that.clientSessionVars.apiClientId + that.clientSessionVars.secret + that.defaultVars.apiKey);
265
                    } else {
266
                        reject('callMethod(): requires initialization. Not initialized');
267
                        return;
268
                    }
269
                }
270
271
                // Create a valid http Request
272
                let reqOptions = {
273
                    url: that.defaultVars.apiUrl,
274
                    formData: reqParams,
275
                    headers: {
276
                        'User-Agent': that.defaultVars.clientName
277
                    }
278
                };
279
280
                // Some command require adding a cookie, we'll do that here
281
                if (options.cookies) {
282
                    let j = request.jar();
283
                    for (let variable in options.cookies) {
284
                        if (options.cookies.hasOwnProperty(variable)) {
285
                            let cookieString = variable + '=' + options.cookies[variable];
286
                            let cookie = request.cookie(cookieString);
287
                            j.setCookie(cookie, that.defaultVars.baseUrl);
288
                        }
289
                    }
290
                    reqOptions.jar = j;// Adds cookies to the request
291
                }
292
293
                request.post(
294
                    reqOptions,
295
                    function (error, response, body) {
296
                        if (!error && response.statusCode === 200) {
297
                            resolve(JSON.parse(body));
298
                        } else {
299
                            //console.log('No response');
300
                            reject('callMethod(): no response.');
301
                        }
302
                    }
303
                );
304
            } catch (e) {
305
                reject(e);
306
            }
307
        });
308
    }
309
310
    /**
311
     * Attempts to log in a user.
312
     * @param {string} username - Username
313
     * @param {string} password - clear text password TODO need to secure this more?
314
     * @param {object=} options
315
     * @param {string=} options.username - Ignore, already required at username
316
     * @param {string=} options.password - Ignore, already required at password
317
     * @returns {Promise<UserVars>}
318
     * @fulfill {UserVars}
319
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
320
     */
321
    async login(username, password, options) {
322
        options = options || {};
323
        options.username = username || options.username || '';
324
        options.password = md5(password || options.password || '');
325
        return await this.loginMD5('', '', options);
326
    }
327
328
    /**
329
     *
330
     * Attempts to log in a user. Requires the password to be pre md5 hashed.
331
     * @param {string} username - Username
332
     * @param {string} password - MD5 hashed password TODO need to secure this more?
333
     * @param {object=} options
334
     * @param {string=} options.username - Ignore, already required at username
335
     * @param {string=} options.password - Ignore, already required at password
336
     * @returns {Promise<UserVars>}
337
     * @fulfill {UserVars}
338
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
339
     */
340
    async loginMD5(username, password, options) {
341
        let that = this;
342
        options = options || {};
343
        options.username = username || options.username || {};
344
        options.password = password || options.password || {};
345
        return new Promise(async function (resolve, reject) {
346
            try {
347
                let response = await that.callMethod(
348
                    {
349
                        method: 'login_login',
350
                        params: {
351
                            vb_login_username: options.username || '',
352
                            vb_login_md5password: options.password || ''
353
                        }
354
                    }
355
                );
356
                /**
357
                 redirect_login - (NOT A ERROR) Login successful
358
                 badlogin - Username or Password incorrect. Login failed.
359
                 badlogin_strikes - Username or Password incorrect. Login failed. You have used {X} out of 5 login attempts. After all 5 have been used, you will be unable to login for 15 minutes.
360
                 */
361
                let error = that.constructor.parseErrorMessage(response);
362
                if (response.session) {
363
                    that.userSessionVars = response.session;
364
                    if (error === 'redirect_login') {
365
                        that.userSessionVars.username = options.username;
366
                        that.userSessionVars.loggedIn = true;
367
                    }
368
                }
369
                if (error === 'redirect_login') {
370
                    error = null;
371
                }
372
                if (error === null) {
373
                    resolve(that.userSessionVars);
374
                } else {
375
                    reject(error);
376
                }
377
378
            } catch (e) {
379
                reject(e);
380
            }
381
        });
382
    }
383
384
    /**
385
     * Attempts to log the user out.
386
     * @returns {Promise<boolean>} - Returns true on success, otherwise error code is rejected
387
     * @fulfill {boolean}
388
     * @reject {string} - Error Reason
389
     */
390
    async logout() {
391
        let that = this;
392
        return new Promise(async function (resolve, reject) {
393
            let error;
394
            try {
395
                let response = await that.callMethod({
396
                    method: 'login_logout'
397
                });
398
                error = that.constructor.parseErrorMessage(response);
399
                if (response.session) {
400
                    that.userSessionVars = response.session;
401
                    if (error === 'cookieclear') {
402
                        that.userSessionVars.username = '';
403
                        that.userSessionVars.loggedIn = false;
404
                    }
405
                }
406
                if (error === 'cookieclear') {
407
                    error = null;
408
                }
409
            } catch (e) {
410
                reject(e);
411
            }
412
413
            if (error) {
414
                reject(error);
415
            } else {
416
                resolve(true)
417
            }
418
        });
419
    }
420
421
    /**
422
     *
423
     * @param {object} response - Response object from callMethod()
424
     * @returns {string || null} status - Error message
425
     */
426
    static parseErrorMessage(response) {
427
        let retur = '';
428
        if (
429
            response.hasOwnProperty('response')
430
            && response.response.hasOwnProperty('errormessage')
431
        ) {
432
            if (_.isArray(response.response.errormessage)) {
433
                retur = response.response.errormessage[0]
434
            } else {
435
                retur = response.response.errormessage;
436
            }
437
        }
438
        return retur;
439
    }
440
441
    /**
442
     * List every Forum and sub forum available to the user.
443
     * @returns {Promise<Forum[]>} - Array of Forum objects
444
     * @fulfill {Forum[]}
445
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
446
     */
447
    getForums() {
448
        return Forum.getHome(this);
449
    }
450
451
    /**
452
     * List detailed info about a forum and it's sub-forums and threads
453
     * @param {number} forumId - Forum id
454
     * @param {object=} options - Secondary Options
455
     * @param {number=} options.forumid - Ignore, already required at forumId
456
     * TODO note additional options
457
     * @returns {Promise<Forum>} - Returns a Forum object
458
     * @fulfill {Forum}
459
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
460
     */
461
    getForum(forumId, options) {
462
        return Forum.get(this, forumId, options);
463
    }
464
465
466
    /**
467
     * Attempts to submit a new Post into a specified Thread
468
     * @param {number} threadId - Thread id
469
     * @param {string} message - Post Message
470
     * @param {object=} options
471
     * @param {boolean=} options.signature  - Optionally append your signature
472
     * @param {number=} options.threadid - Ignore, already required at threadId
473
     * @param {string=} options.message - Ignore, already required at message
474
     * TODO note additional options
475
     * @returns {Promise<*>} - Returns a unhandled response currently
476
     * @fulfill {*}
477
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
478
     */
479
    createPost(threadId, message, options) {
480
        return Post.create(this, threadId, message, options);
481
    }
482
483
    /**
484
     * @deprecated as of 1.4.1
485
     * @see createPost
486
     */
487
    newPost(threadId, message, options) {
488
        return Post.create(this, threadId, message, options);
489
    }
490
491
    /**
492
     * Attempts to edit an existing Post
493
     * @param {number} postId - Post id
494
     * @param {string} message - Post Message
495
     * @param {object=} options
496
     * @param {string=} options.reason - Reason for editing
497
     * @param {boolean=} options.signature - Optionally append your signature
498
     * @param {number=} options.postid - Ignore, already required at postId
499
     * @param {string=} options.message - Ignore, already required at message
500
     * TODO note additional options
501
     * @returns {Promise<*>} - Returns a unhandled response currently
502
     * @fulfill {*}
503
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
504
     */
505
    editPost(postId, message, options) {
506
        return Post.edit(this, postId, message, options);
507
    }
508
509
    /**
510
     * TODO untested - does not seem to function yet
511
     * Attempts to delete an existing Post
512
     * @param {number} postId - Post id
513
     * @param {number} threadId - Thread id
514
     * @param {object=} options
515
     * @param {string=} options.reason - Reason for deleting
516
     * @param {number=} options.postid - Ignore, already required at postId
517
     * @param {number=} options.threadid - Ignore, already required at threadId
518
     * TODO note additional options
519
     * @returns {Promise<*>} - Returns a unhandled response currently
520
     * @fulfill {*}
521
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
522
     */
523
    deletePost(postId, threadId, options) {
524
        return Post.delete(this, postId, threadId, options);
525
    }
526
527
    /**
528
     * List detailed information about a Thread and it's Posts
529
     * @param {number} threadId - Thread id
530
     * @param {object=} options - Secondary Options
531
     * @param {number=} options.threadid - Ignore, already required at threadId
532
     * TODO note additional options
533
     * @returns {Promise<Thread>} - Returns a Thread object
534
     * @fulfill {Thread}
535
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
536
     */
537
    getThread(threadId, options) {
538
        return Thread.get(this, threadId, options);
539
    }
540
541
    /**
542
     * Attempts to submit a new Thread into a specified Forum. This will also be considered the first Post
543
     * @param {number} forumId - Forum Id
544
     * @param {string} subject - Post/Thread Subject
545
     * @param {string} message - Post Message
546
     * @param {object=} options
547
     * @param {boolean=} options.signature - Optionally append your signature
548
     * @param {number=} options.forumid - Ignore, already required at postId
549
     * @param {string=} options.subject - Ignore, already required at postId
550
     * @param {string=} options.message - Ignore, already required at postId
551
     * TODO note additional options
552
     * @returns {Promise<*>} - Returns a unhandled response currently
553
     * @fulfill {*}
554
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
555
     */
556
    createThread(forumId, subject, message, options) {
557
        return Thread.create(this, forumId, subject, message, options);
558
    }
559
560
    /**
561
     * @deprecated as of 1.4.1
562
     * @see createThread
563
     */
564
    newThread(forumId, subject, message, options) {
565
        return Thread.create(this, forumId, subject, message, options);
566
    }
567
568
    /**
569
     * TODO incomplete - does not seem to function yet
570
     * Attempts to close a specific Thread. Requires a user to have a 'inline mod' permissions
571
     * @param {number} threadId - Id of Thread to close
572
     * @returns {Promise<*>} - Returns a unhandled response currently
573
     * @fulfill {*}
574
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
575
     */
576
    closeThread(threadId) {
577
        return Thread.close(this, threadId);
578
    }
579
580
    /**
581
     * TODO incomplete - does not seem to function yet
582
     * Attempts to open a specific Thread. Requires a user to have a 'inline mod' permissions
583
     * @param {number} threadId - Id of Thread to open
584
     * @returns {Promise<*>} - Returns a unhandled response currently
585
     * @fulfill {*}
586
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
587
     */
588
    openThread(threadId) {
589
        return Thread.open(this, threadId);
590
    }
591
592
    /**
593
     * TODO incomplete - does not seem to function yet
594
     * Attempts to delete a specific Thread. Requires a user to have a 'inline mod' permissions
595
     * @param {number} threadId - Id of Thread to close
596
     * @returns {Promise<*>} - Returns a unhandled response currently
597
     * @fulfill {*}
598
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
599
     */
600
    deleteThread(threadId) {
601
        return Thread.delete(this, threadId);
602
    }
603
604
    /**
605
     * @deprecated as of 1.3.1
606
     * @see closeThread
607
     */
608
    modCloseThread(threadId) {
609
        return Thread.close(this, threadId);
610
    }
611
612
    /**
613
     * @deprecated as of 1.3.1
614
     * @see openThread
615
     */
616
    modOpenThread(threadId) {
617
        return Thread.open(this, threadId);
618
    }
619
620
    /**
621
     * @deprecated as of 1.3.1
622
     * @see deleteThread
623
     */
624
    modDeleteThread(threadId) {
625
        return Thread.delete(this, threadId);
626
    }
627
628
    /**
629
     * Get logged in user's Inbox and list of private Messages
630
     * @param {object=} options
631
     * @returns {Promise<Inbox>} - Returns an Inbox object
632
     * @fulfill {Inbox}
633
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
634
     */
635
    getInbox(options) {
636
        return Inbox.get(this, options);
637
    }
638
639
    /**
640
     * Attempts to submit a new Thread into a specified Forum. This will also be considered the first Post
641
     * @param {Date} date - Delete all messages from before the specified date
642
     * @param {number=0} folderId - Folder Id, defaults to 0
643
     * @param {object=} options
644
     * @param {string=} options.dateline - Ignore, already required at date
645
     * @param {number=} options.folderid - Ignore, already required at folderId
646
     * TODO note additional options
647
     * @returns {Promise<void>} - Returns a unhandled response currently
648
     * @fulfill {void}
649
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
650
     */
651
    emptyInbox(date, folderId, options) {
652
        return Inbox.empty(this, date, folderId, options)
653
    }
654
655
    /**
656
     * Get details of a specific Message for the logged in user
657
     * @param {number} id
658
     * @param {object=} options
659
     * @param {number=} options.pmid - Ignore, already required at id
660
     * @returns {Promise<Message>} - Returns a Message object
661
     * @fulfill {Message}
662
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
663
     */
664
    getMessage(id, options) {
665
        return Message.get(this, id, options);
666
    }
667
668
    /**
669
     *
670
     * @param {string} username - Username to send the message to
671
     * @param {string} title - Message Subject
672
     * @param {string} message - Message content
673
     * @param {object=} options
674
     * @param {boolean=} options.signature - Optionally append your signature
675
     * @param {string=} options.recipients - Ignore, already required at username
676
     * @param {string=} options.title - Ignore, already required at title
677
     * @param {string=} options.message - Ignore, already required at message
678
     * TODO note additional options
679
     * @returns {Promise<void>} - Successfully completes if sent. TODO: provide a better response
680
     * @fulfill {void}
681
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
682
     */
683
    createMessage(username, title, message, options) {
684
        return Message.create(this, username, title, message, options)
685
    }
686
687
    /**
688
     * @deprecated as of 1.4.1
689
     * @see createMessage
690
     */
691
    sendMessage(username, title, message, options) {
692
        return Message.create(this, username, title, message, options)
693
    }
694
695
    /**
696
     * Attempts to retrieve data about a specific user found by username
697
     * @param {string} username - Username
698
     * @param {object=} options - Secondary Options
699
     * @param {string=} options.username - Ignore, already required at username
700
     * @returns {Promise<Member>} - Returns a Member object
701
     * @fulfill {Member}
702
     * @reject {string} - Error Reason. Expects: (TODO list common errors here)
703
     */
704
    getMember(username, options) {
705
        return Member.get(this, username, options);
706
    }
707
}
708
709
module.exports = VBApi;
710